package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.rule.AbstractDynamicRuleService;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.config.NacosProperties;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Objects;

/**
 * DynamicRuleNacosService
 *
 * @author kancy
 * @date 2020/5/4 15:03
 */
abstract class DynamicRuleNacosService<T> extends AbstractDynamicRuleService<T> {
    private static final Logger log = LoggerFactory.getLogger(DynamicRuleNacosService.class);

    @Autowired
    private ConfigService configService;
    @Autowired
    private NacosProperties nacosProperties;

    /**
     * Publish rules to remote rule configuration center for given application name.
     *
     * @param app   app name
     * @param rules list of rules to push
     * @throws Exception if some error occurs
     */
    @Override
    public void publish(String app, List<T> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (Objects.isNull(rules)) {
            return;
        }

        String dataId = getDataId(app);
        String groupId = nacosProperties.getGroupId();
        String configRules = serialize(rules);
        configService.publishConfig(dataId, groupId, configRules);
        log.info("Publish [{}] flowRule to naocs config : {}", app, configRules);
    }


    /**
     * 获取规则
     * @param appName
     * @return
     * @throws Exception
     */
    @Override
    public List<T> getRules(String appName) throws Exception {
        String dataId = getDataId(appName);
        String groupId = nacosProperties.getGroupId();
        String rules = configService.getConfig(dataId, groupId, nacosProperties.getReadTimeoutMs());
        log.debug("Pull [{}] flowRule from nacos config : {}", appName, rules);
        return deserialize(rules);
    }

    /**
     * 获取数据ID
     * @param appName
     * @return
     */
    protected abstract String getDataId(String appName);


    /**
     * 获取外部化属性
     * @return
     */
    protected NacosProperties getNacosProperties() {
        return nacosProperties;
    }
}
